/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function createErrorType(name, init, superErrorClass = Error) {
    function JsJodaException(message) {
        if (!Error.captureStackTrace) {
            this.stack = (new Error()).stack;
        } else {
            Error.captureStackTrace(this, this.constructor);
        }
        this.message = message;
        init && init.apply(this, arguments);
        this.toString = function () {
            return `${this.name}: ${this.message}`;
        };
    }
    JsJodaException.prototype = Object.create(superErrorClass.prototype);
    JsJodaException.prototype.name = name;
    JsJodaException.prototype.constructor = JsJodaException;
    return JsJodaException;
}

export const DateTimeException = createErrorType('DateTimeException', messageWithCause);
export const DateTimeParseException = createErrorType('DateTimeParseException', messageForDateTimeParseException);
export const UnsupportedTemporalTypeException = createErrorType('UnsupportedTemporalTypeException', null, DateTimeException);
export const ArithmeticException = createErrorType('ArithmeticException');
export const IllegalArgumentException = createErrorType('IllegalArgumentException');
export const IllegalStateException = createErrorType('IllegalStateException');
export const NullPointerException = createErrorType('NullPointerException');

function messageWithCause(message, cause = null) {
    let msg = message || this.name;
    if (cause !== null && cause instanceof Error) {
        msg += `\n-------\nCaused by: ${cause.stack}\n-------\n`;
    }
    this.message = msg;
}

function messageForDateTimeParseException(message, text = '', index = 0, cause = null) {
    let msg = message || this.name;
    msg += `: ${text}, at index: ${index}`;
    if (cause !== null && cause instanceof Error) {
        msg += `\n-------\nCaused by: ${cause.stack}\n-------\n`;
    }
    this.message = msg;
    this.parsedString = () => {
        return text;
    };
    this.errorIndex = () => {
        return index;
    };
}
